package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.*;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @version 1.0
 * @Author 杨旭康
 * @Date 2022/10/27 23:54
 * @question:
 */

@Service
@Slf4j
//事务,多表操作
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishFlavorMapper dishFlavorMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;
    @Autowired
    private SetmealMapper setmealMapper;

    /**
     * 保存 菜品和口味
     *
     * @param dishDto
     */
    @Override
    @Transactional
    public void saveWithFlavor(DishDto dishDto) {

        //直接保存菜品信息(dishDto继承了dish)
        this.save(dishDto);

        //获得菜品id
        Long dishId = dishDto.getId();

        //通过dto获得前端传来的口味信息(集合) ===>> 设置上菜品id 口味表
        List<DishFlavor> flavors = dishDto.getFlavors();
        //遍历设置
        flavors = flavors.stream().map((item) -> {
            item.setDishId(dishId);
            return item;
        }).collect(Collectors.toList());

        //保存菜品口味数据到菜品口味表dish_flavor
        for (DishFlavor flavor : flavors) {
            dishFlavorMapper.insert(flavor);
        }

    }

    /**
     * 分页条件查询
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public Page<DishDto> dishDtoPage(int page, int pageSize, String name) {

        //菜品分来 ==>> 满足不了页面要求 categoryName
        Page<Dish> pageInfo = new Page<>(page, pageSize);
        //dto数据传输对象分页
        Page<DishDto> dishDtoPage = new Page<>();

        //构造条件
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //模糊查询
        wrapper.like(StringUtils.isNotEmpty(name), Dish::getName, name);
        //进行排序
        wrapper.orderByDesc(Dish::getUpdateTime).orderByAsc(Dish::getSort);

        //记着调用方法查询 否则不会生效
        pageInfo = dishMapper.selectPage(pageInfo, wrapper);

        //使用对拷 将dish数据传输到dto(页面值都在record上 total直接拷走分页数据)
        BeanUtils.copyProperties(pageInfo, dishDtoPage, "records");
        //隔离出来的 records 进行遍历设值
        List<Dish> records = pageInfo.getRecords();

        List<DishDto> list = records.stream().map((item) -> {

            //创建一个空的 dishDto 对象
            DishDto dishDto = new DishDto();
            //此处在进行流的对拷 遍历的每一次 record
            BeanUtils.copyProperties(item, dishDto);

            //获取分类id 调用分类名
            Long categoryId = item.getCategoryId();
            //调用service-->获取名字
            Category category = categoryMapper.selectById(categoryId);

            //可以判断一下分类是否为null
            if (category != null) {
                String categoryName = category.getName();
                //赋值给dto
                dishDto.setCategoryName(categoryName);
            }
            return dishDto;
        }).collect(Collectors.toList());

        //完成之后重新赋值给 dtoPage
        dishDtoPage.setRecords(list);

        return dishDtoPage;
    }

    /**
     * 查询--回显
     *
     * @param id
     * @return
     */
    @Override
    public DishDto getByIdWithFlavor(Long id) {

        DishDto dishDto = new DishDto();

        Dish dish = dishMapper.selectById(id);
        //对dish和dto进行对拷
        BeanUtils.copyProperties(dish, dishDto);

        //口味列表 ==>> 设置值装入集合
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        //进行个等值比较 id
        wrapper.eq(DishFlavor::getDishId, dish.getId());
        List<DishFlavor> list = dishFlavorMapper.selectList(wrapper);
        //将集合放入dto
        dishDto.setFlavors(list);

        return dishDto;
    }

    /**
     * 修改
     *
     * @param dishDto
     */
    @Override
    @Transactional
    public void updateWithFlavor(DishDto dishDto) {

        //直接调用菜品修改
        this.updateById(dishDto);
        //开始对口味进行修改 可以分步骤做
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();

        //1.首先全部清除掉口味列表
        //对菜品id进行等值查询 一样直接清除
        wrapper.eq(DishFlavor::getDishId, dishDto.getId());
        dishFlavorMapper.delete(wrapper);

        //2.在重新插入口味列表
        List<DishFlavor> flavors = dishDto.getFlavors();
        for (DishFlavor flavor : flavors) {
            flavor.setDishId(dishDto.getId());
            dishFlavorMapper.insert(flavor);
        }


    }

    /**
     * 批量删除,删除也要记者把口味表数据删掉
     * 删除菜品:1.售卖状态 2.在绑定套餐的情况下不能删除 先将套餐删除才能删除菜品
     *
     * @param ids
     */
    @Override
    @Transactional
    public void removeByIdsWithFlavor(List<Long> ids) {

        //1.查询菜品的售卖状态
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        //状态为1不能删除
        queryWrapper.eq(Dish::getStatus, 1);
        //比较前端传来的id
        queryWrapper.in(Dish::getId, ids);
        //统计满足条件,想要删除的数量
        int count = this.count(queryWrapper);

        if (count > 0) {
            //不能删除
            throw new CustomException("菜品在售卖中无法进行删除操作!");
        }

        //2.在绑定套餐的情况下不能删除 先将套餐删除才能删除菜品(setmeal_dish中的dish_id)
        //select * from setmeal_dish where dish_id = ?
        LambdaQueryWrapper<SetmealDish> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.in(SetmealDish::getDishId, ids);
        //查询符合条件的
        Integer selectCount = setmealDishMapper.selectCount(wrapper1);
        if (selectCount > 0) {
            throw new CustomException("您想要删除的菜品关联了套餐,暂时不能删除");
        }

        //到此处可以进行删除
        for (Long id : ids) {
            //删除菜品
            this.removeById(id);
            //条件判断 删除口味(菜品id更新时,也要创建一个新的wrapper对象)
            LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DishFlavor::getDishId, id);
            //调用service删除口味
            dishFlavorMapper.delete(wrapper);
        }
    }

    /**
     * 在套餐分类中根据套餐分类下拉列表和菜品列表 展示菜品
     *
     * @param dishDto
     * @return
     */
    @Override
    public List<DishDto> listR(DishDto dishDto) {

        //条件构造器
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //进行两次等职比较和排序
        wrapper.eq(dishDto.getCategoryId() != null, Dish::getCategoryId, dishDto.getCategoryId());
        wrapper.eq(Dish::getStatus, 1);
        wrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

        //调用mapper查询 集合
        List<Dish> dishList = dishMapper.selectList(wrapper);

        List<DishDto> dishDtoList = dishList.stream().map((item) -> {
            //创建一个空的dto对象 进行拷贝数据
            DishDto dto = new DishDto();
            BeanUtils.copyProperties(item,dto,"records");

            //获得菜品id
            Long dishId = item.getId();
            //查询方法
            LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
            //将口味数据扔进集合
            List<DishFlavor> dishFlavors = dishFlavorMapper.selectList(lambdaQueryWrapper);
            //dto设置值
            dto.setFlavors(dishFlavors);

            return dto;
        }).collect(Collectors.toList());

        return dishDtoList;
    }

    /**
     * 判断菜品
     * 菜品如果不包含在套餐当中可以直接停售
     * 如果包含在套餐当中 且套餐售卖状态为 1直接抛业务异常
     */
    @Override
    public void status(String status, List<Long> ids) {

        //1.判断菜品状态是否为0 --> 继续往下走
        if ("0".equals(status)) {
            //2.判断 套餐/菜品 状态是否为售卖状态为0 则可以进行停售操作
            //  必须要想办法获得该套餐id才能进行判断
            LambdaQueryWrapper<SetmealDish> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(SetmealDish::getDishId, ids);
            //调用service成集合对象
            List<SetmealDish> setmealDishList = setmealDishMapper.selectList(wrapper);

            //必须要判断 菜品/套餐 确定有关联的数据 才能往下走 否则直接跳出
            //如果获取到的id没有加入套餐的话 往里边走会直接报错
            if (setmealDishList.size() != 0) {
                //想要转换成Setmeal对象
                ArrayList<Long> setmealIds = new ArrayList<>();
                //遍历 setmealDishList 让其setmeal的id 全部装进 setmeal对象
                for (SetmealDish setmealDish : setmealDishList) {
                    setmealIds.add(setmealDish.getSetmealId());
                }

                //调用 setmeal 条件查询器
                LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
                //查询所有ids
                queryWrapper.in(Setmeal::getId, setmealIds);
                //等值查询条件为1的对象
                queryWrapper.eq(Setmeal::getStatus, 1);
                //调用service
                int count = setmealMapper.selectCount(queryWrapper);

                if (count > 0) {
                    //有状态为1的 抛业务异常
                    throw new CustomException("当前菜品关联了套餐属性,不能停售");
                }
            }
        }

        //3.前二个条件都满足了 可以执行 停售/起售 操作
        List<Dish> list = new ArrayList<>();
        for (Long id : ids) {
            Dish dish = dishMapper.selectById(id);
            //停售/起售 都可以操作
            dish.setStatus(Integer.parseInt(status));
            list.add(dish);
        }
        for (Dish dish : list) {
            dishMapper.updateById(dish);
        }
    }


}
